﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using Ams.Extensions;

namespace Ams.Mvc.Bootstrap
{
    public static class BootstrapInputExtensions
    {
        #region CheckBoxFor 
        internal static MvcHtmlString CheckBoxFor<TModel,TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
        {
            var modelType = helper.ViewData.Model.GetType();


            var parameterExpression = Expression.Parameter(modelType, "x");
            var propertyAccess = Expression.MakeMemberAccess(parameterExpression, expression.GetPropertyInfo());

            var lambdaExpression = typeof(Expression).GetMethods().Where(i => i.Name == "Lambda" && i.GetParameters().Count() == 2).ToArray()[0];
            
            var funcType = typeof(Func<,>).MakeGenericType(new[] { modelType, typeof(bool) });
            var lambdaGeneric = lambdaExpression.MakeGenericMethod(new[] { funcType });
            var compatibleExpression = lambdaGeneric.Invoke(null, new object[] { propertyAccess, new[] { parameterExpression } });

            var m = typeof(BootstrapInputExtensions).GetMethod("CheckBoxFor").MakeGenericMethod(new[] { modelType, typeof(bool) });
            return (MvcHtmlString)m.Invoke(null, new object[] { helper, compatibleExpression });
        }
        public static MvcHtmlString CheckBoxFor<TModel>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, bool>> expression)
        {
            return CheckBoxFor(helper, expression, null);
        }
        public static MvcHtmlString CheckBoxFor<TModel>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, bool>> expression, object htmlAttributes)
        {
            return CheckBoxFor(helper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }
        public static MvcHtmlString CheckBoxFor<TModel>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, bool>> expression, IDictionary<string, object> htmlAttributes)
        {
            htmlAttributes = htmlAttributes ?? new Dictionary<string, object>();
            HtmlMod.AppendToAttributeList(ref htmlAttributes, "class", "form-control");
            var html = InputExtensions.CheckBoxFor(helper.Html, expression, htmlAttributes).ToString();
            
            if (helper.Form != null)
            {
                var label = new TagBuilder("label");
                label.InnerHtml = html + expression.GetPropertyInfo().DisplayName();

                var checkboxDiv = new TagBuilder("div");
                checkboxDiv.AddCssClass("checkbox");
                checkboxDiv.InnerHtml = label.ToString();

                if (helper.Form.FormType == Form.Horizontal)
                {
                    var div = new TagBuilder("div");
                    div.AddCssClass("col-sm-offset-2 col-sm-10");
                    div.InnerHtml = checkboxDiv.ToString();

                    var formGroup = new TagBuilder("div");
                    formGroup.AddCssClass("form-group");
                    formGroup.InnerHtml = div.ToString();

                    html = formGroup.ToString();
                }
                else
                {
                    html = checkboxDiv.ToString();
                }
            }

            return new MvcHtmlString(html);
        }
        #endregion

        #region HiddenFor
        public static MvcHtmlString HiddenFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
        {
            return HiddenFor(helper, expression, null);
        }

        public static MvcHtmlString HiddenFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return HiddenFor(helper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString HiddenFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
        {
            var html = InputExtensions.HiddenFor(helper.Html, expression, htmlAttributes);
            return html;
        }
        #endregion

        #region TextBoxFor
        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
        {
            return TextBoxFor(helper, expression, (IDictionary<string, object>)null);
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string format)
        {
            return TextBoxFor(helper, expression, format, null);
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return TextBoxFor(helper, expression, null, htmlAttributes);
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string format, object htmlAttributes)
        {
            return TextBoxFor(helper, expression, format, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
        {
            return TextBoxFor(helper, expression, null, htmlAttributes);
        }

        public static MvcHtmlString TextBoxFor<TModel, TProperty>(this BootstrapHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string format, IDictionary<string, object> htmlAttributes)
        {
            htmlAttributes = htmlAttributes ?? new Dictionary<string, object>();
            HtmlMod.AppendToAttributeList(ref htmlAttributes, "class", "form-control");

            var html = InputExtensions.TextBoxFor(helper.Html, expression, format, htmlAttributes);
            
            if (helper.Form != null && helper.Form.FormType == Form.Horizontal)
            {
                var divWrapper = new TagBuilder("div");
                divWrapper.AddCssClass(helper.Form.EditorClasses);
                divWrapper.InnerHtml = html.ToString();
                html = divWrapper.ToMvcHtmlString();
            }
            
            return html;
        }
        #endregion
    }
}
